/****************************************************************************
**
** Copyright (C) 2011 Jesús Martínez Pérez
**
** This program is free software: you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the 
** Free Software Foundation, either version 3 of the License, or (at your
** option) any later version.
**
** This program is distributed in the hope that it will be useful, but 
** WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
** or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
** for more details.
**
** You should have received a copy of the GNU General Public License along 
** with this program. If not, see <http://www.gnu.org/licenses/>
**
****************************************************************************/
#include <vbits.h>


Vbits::Vbits(){
	n=0;
}


Vbits::Vbits(int t){
	if(t!=0){
		for(int i=0;i<=t/8;i++)
			vd.Add(0);
		}
	n=t;
}


Vbits::Vbits(VD_unsignedchar vd1){
	vd=vd1;
	n=vd1.Size()*8;
}


Vbits::Vbits(int nu,int bits){
	Vbits vbit;
	for(int i=0;nu!=0;i++){
		vbit.Add(nu%2);
		nu=nu/2;
	}
	int l=vbit.n;
	for(int i=0;i<bits-l;i++){
		vbit.Add(0);
	}
	*this=vbit;
}


int Vbits::tamV(){
	return vd.Size();
}


unsigned char Vbits::Getv(int pos)const{
	return vd.Get(pos);
}


unsigned long int Vbits::Size()const{
	return n;
}


void Vbits::Invertir(){
	Vbits vb(0);
	for(int i=n-1;i>=0;i--){
		vb.Add(Get(i));
	}
	*this=vb;
}


void Vbits::Completar(){
	while(n%8!=0){
		Add(0);
	}
}


void Vbits::Add(bool b){
	if(n%8==0){
		unsigned char byte=0;
		if(b){
			byte=1;
		}
		vd.Add(byte);
	}
	else{
		unsigned char byte=vd.Get(vd.Size()-1);
		if(b){
			byte=(byte|(1<<(n%8)));
		}
		vd.Set(vd.Size()-1,byte);
	}
	n++;
}


bool Vbits::Get(int i)const{
	unsigned char byte;
	byte=vd.Get(i/8);
	return ((byte &(1<<(i%8)))?1:0);
}


void Vbits::Set(bool b,int i){
	unsigned char byte=vd.Get(i/8);
	if(byte &(1<<(i%8)))
		if(!b){
			byte=(byte^(1<<(i%8)));
		}
	if(!(byte &(1<<(i%8))))
		if(b)
			byte=(byte|(1<<(i%8)));
	vd.Set(i/8,byte);
}


Vbits & Vbits::operator+=(const bool b){
	unsigned char byte=0;	
	(b)?byte=1,Add(byte):Add(byte);
	return *this;
}


Vbits & Vbits::operator=(const Vbits &v){
	if(this!=&v){
		vd=v.vd;
		n=v.n;
	}
	return *this;
}


Vbits & Vbits::operator+=(const Vbits & v){
	for(unsigned long int i=0;i<v.n;i++){
		bool b = v.Get(i);
		Add(b);
	}
	return *this;
}


bool Vbits::operator==(const Vbits &v){
	bool iguales = false;
	if(n==v.n){
		iguales=true;
		for(unsigned long int i=0;((i<n) && (iguales==true));i++){
			if(v.Get(i)!=Get(i))
				iguales=false;
		}
		return iguales;
	}
	return iguales;
}


bool Vbits::operator!=(const Vbits &v){
	return !(*this==v);
}


ostream & operator<<(ostream & os, const Vbits &v){
		for(unsigned long int i=0;i<v.n;i++){
			os<<v.Get(i);
		}
	return os;
}


istream & operator>>(istream & is,Vbits & v){
	int num;
	is>>num;
	for(int i=0;i<num;i++){
		bool b;
		is>>b;
		v.Add(b);
	}
	return is;
}
